﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OrganizationName.CodeGeneration;
using OrganizationName.Common;

namespace OrganizationName.Factory
{
    public abstract class CollectionMaterial : AnonymousInstance
    {
        protected bool IsParentCollectionArray(ICodeContext codeContext)
        {
            return GetCollectionType(codeContext).IsArray;
        }

        protected bool IsParentCollectionList(ICodeContext codeContext)
        {
            return GetCollectionKeyAndElementTypes(codeContext).Length == 1;
        }

        protected bool IsParentCollectionDictionary(ICodeContext codeContext)
        {
            return GetCollectionKeyAndElementTypes(codeContext).Length == 2;
        }

        protected System.Type[] GetCollectionKeyAndElementTypes(ICodeContext codeContext)
        {
            try
            {
                return Utility.GetCollectionKeyAndElementTypes(GetCollectionType(codeContext));
            }
            catch (Exception collectionDeterminationError)
            {
                throw new CodeGenerationException("An error occured during determination of the key and value types of the collection", codeContext, collectionDeterminationError);
            }
        }

        protected virtual System.Type GetCollectionKeyType(ICodeContext codeContext)
        {
            System.Type[] collectionKeyAndElementType = GetCollectionKeyAndElementTypes(codeContext);

            if (collectionKeyAndElementType.Length != 2)
            {
                throw new CodeGenerationException("Collection key type cannot be determined for type " + GetCollectionType(codeContext) + ". The type is not a supported key/value collection", codeContext, null);
            }

            return collectionKeyAndElementType[0];
        }

        protected virtual System.Type GetCollectionValueType(ICodeContext codeContext)
        {
            System.Type[] collectionKeyAndElementType = Utility.GetCollectionKeyAndElementTypes(GetCollectionType(codeContext));
            return collectionKeyAndElementType[collectionKeyAndElementType.Length - 1];
        }

        protected abstract System.Type GetCollectionType(ICodeContext codeContext);

    }
}
